﻿
namespace CmdArgs
{
    using System.ComponentModel;
    using System.Globalization;

    /// <summary>
    /// Represents one option value.
    /// </summary>
    /// <remarks>
    /// Option value is represented as string, 
    /// but this class provides methods for converting 
    /// it into other types.
    /// Custom types might be also supported,
    /// because generic method <see cref="As{T}"/> uses    
    /// <see cref="System.ComponentModel.TypeDescriptor"/> 
    /// which may be extended with custom converters.
    /// </remarks>
    public sealed class OptionParameterValue
    {
        internal OptionParameterValue(string value)
        {
            this.Value = value;
        }

        /// <summary>
        /// Gets the raw value of option.
        /// </summary>
        public string Value { get; private set; }

        /// <summary>
        /// Alias for <see cref="Value"/>.
        /// </summary>
        /// <returns>The <see cref="Value"/>.</returns>
        public string AsString()
        {
            return this.Value;
        }

        /// <summary>
        /// Parses option value using int.Parse.
        /// </summary>
        /// <returns>The <see cref="Value"/> converted to integer.</returns>
        public int AsInt()
        {
            return int.Parse(this.Value, NumberStyles.Integer);
        }

        /// <summary>
        /// Parses option value using double.Parse.
        /// </summary>
        /// <returns>The <see cref="Value"/> converted to double.</returns>
        public double AsDouble()
        {
            return double.Parse(this.Value, NumberStyles.Float);
        }

        /// <summary>
        /// Returns option value as boolen. 
        /// Strings "true" in any casing ("TRUE", "True", ...) and "1" 
        /// are converted to <c>true</c>, others are converted to <c>false</c>.
        /// </summary>        
        /// <returns>The <see cref="Value"/> as boolean.</returns>
        public bool AsBool()
        {
            return this.Value.ToUpperInvariant() == "TRUE" || this.Value == "1";
        }

        /// <summary>
        /// Converts option value using convertor that is returned by
        /// <see cref="System.ComponentModel.TypeDescriptor.GetConverter(Type)"/>.
        /// </summary>
        /// <typeparam name="T">The target type.</typeparam>
        /// <returns>The <see cref="Value"/> as given type.</returns>
        public T As<T>()
        {
            return (T)TypeDescriptor
                .GetConverter(typeof(T))                
                .ConvertFromInvariantString(this.Value);
        }

        /// <summary>
        /// This method is overriden to return the option value raw
        /// content as <see cref="Value"/> or <see cref="AsString"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.Value;
        }
    }
}
